Datadog による Amazon ECS on AWS Fargate コンテナログ収集のベストプラクティス
こんにちは。テクニカルサポートチームのShiinaです。
はじめに
コンテナ環境でのアプリケーション運用において、ログの収集と監視は非常に重要です。
エラーの早期発見や原因調査、セキュリティインシデントの検知など、様々な用途で活用されます。
本記事では、Amazon ECS on AWS Fargate で実行されているコンテナのログを Datadog で収集する2つの方法について、それぞれの特徴や具体的な設定手順を解説します。
AWS FireLens を利用する方法と、CloudWatch Logs 経由で Datadog Forwarder を使用する方法を比較しながら、実装に必要なポイントを説明していきます。
ログの収集方法
Amazon ECS on AWS Fargate で実行されているコンテナログを収集して Datadog に転送する方法は2種類あります。
- AWS FireLens を利用する方法(Datadog 推奨)
- CoudWatch Logs に出力したログを Datadog Forwarder でルーティングする方法
収集方法の比較
AWS FireLens を利用する方法
- メリット
・リアルタイム性が高く、CloudWatch Logs のコストが不要
・専用パイプラインを利用できるため、検索性・可視性が向上 - デメリット
・設定が難しく、Fluent Bit の知識が必要
・log router コンテナの管理が必要
CoudWatch Logs に出力したログを Datadog Forwarder でルーティングする方法
- メリット
・設定が簡単で AWS 標準の運用に適合
・他の AWS サービスとの連携が可能 - デメリット
・レイテンシーが高く、追加コストが発生
・検索性・可視性向上にはパイプライン設定が必要
選択のポイント
・コスト重視・リアルタイム性 → AWS FireLens を利用する方法
・シンプルさ・AWS 標準運用 → CoudWatch Logs に出力したログを Datadog Forwarder でルーティングする方法
実際の監視要件や運用要件に照らし合わせて選択してください。
事前準備
いずれのログ収集方法でも共通して必要となる設定を事前に行なっておきます。
1.Datadog API キーのシークレット登録
コンテナの環境変数やオプションパラメータに Datadog API キーを指定する際は、情報を直接含めないことが重要です。
AWS Secrets Manager に Datadog API キーを登録し、シークレット値を参照する形で安全に利用するのがベストプラクティスです。
AWS Secrets Manager メニューのシークレットより、「新しいシークレットを保存する」を選択します。
次のように設定の上、シークレットを登録します。
- シークレットタイプ:その他のシークレットのタイプ
- キー/値のペア:プレーンテキスト
{"":""}をクリアし、Datadog API キーを入力します。 - シークレットの名前
任意の名前を入力します。 - ローテーションを設定
オプションの設定不要です。
登録後はシークレット一覧より名前を選択し、シークレットの ARN を確認します。
設定手順で利用する場面がありますので ARN は控えておいてください。
2.タスク実行ロール作成
Amazon ECS on AWS Fargate コンテナメトリクスやログ収集に必要となるタスク実行ロールを作成します。
IAM メニューのロールより、「ロールの作成」を選択します。
次のように設定の上、ロールを作成します。
- サービスまたはユースケース:Elastic Container Service
- ユースケース:Elastic Container Service Task
- 許可ポリシー:AmazonECSTaskExecutionRolePolicy
ロール作成後、上記マネージドポリシーに不足している、次の権限はインラインポリシーにて追加を行います。
- CloudWatch Logs ロググループ作成に必要なアクセス
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup"
],
"Resource": [
"*"
]
}
]
}
- Datadog エージェントが Amazon ECS on AWS Fargate コンテナメトリクス収集に必要なアクセス
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ecs:ListContainerInstances",
"ecs:DescribeContainerInstances",
"ecs:ListClusters"
],
"Resource": "*"
}
]
}
- AWS Secrets Manager からシークレット値の取得に必要なアクセス
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:xxxxxxxxxxx"
}
]
}
3.タスク実行ロール設定
タスク定義パラメータのexecutionRoleArn
パラメータに作成したタスク実行ロールの ARN を指定します。
{
"taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:xxxxxxxxxxxx:task-definition/xxxxxx:nn",
"containerDefinitions": [
(中略)
],
"family": "FireLens",
"executionRoleArn": "arn:aws:iam::xxxxxxxxxxxx:role/xxxxxxxxx",
(中略)
AWS FireLens を利用する方法
設定の流れ
Fluent Bit を使用した FireLens ログルーターコンテナをタスク定義に追加します。
アプリケーションコンテナのログを AWS FireLens 経由で Datadog のログエンドポイントに送信する設定を行います。
必要に応じて、Datadog サイドカーコンテナにも同様のログ構成を適用します。
1.Fluent Bit FireLens ログルーターコンテナ追加
タスク定義パラメータのcontainerDefinitions
にコンテナを追加します。
イメージはpublic.ecr.aws/aws-observability/aws-for-fluent-bit:stable
を利用します。
なお、ログルータコンテナ自体のログは awslogs ログドライバーで CoudWatch Logs に出力となります。
firelensConfiguration
パラメータ
・type
パラメータはfluentbit
を指定します。
・options のenable-ecs-log-metadata
はtrue
を指定します。logConfiguration
パラメータ
・ログドライバーはawslogs
を指定します。
・options のawslogs-group
awslogs-region
awslogs-stream-prefix
パラメータで出力先となる リージョン、CloudWatchLogs ロググループ名、プレフィックスを指定します。
(中略)
{
"name": "log_router",
"image": "public.ecr.aws/aws-observability/aws-for-fluent-bit:stable",
"cpu": 0,
"memoryReservation": 51,
"portMappings": [],
"essential": true,
"environment": [],
"mountPoints": [],
"volumesFrom": [],
"user": "0",
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/ecs-aws-firelens-sidecar-container",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "firelens"
},
"secretOptions": []
},
"systemControls": [],
"firelensConfiguration": {
"type": "fluentbit",
"options": {
"enable-ecs-log-metadata": "true"
}
}
}
(中略)
2.アプリケーションコンテナのログ構成設定
アプリケーションコンテナの例として、nginx に対するログ構成設定を行います。
logConfiguration
パラメータ
・ログドライバーはawsfirelen
を指定します。
・options
パラメータでは下表の Datadog オプションを追加します。
・secretOptions
パラメータでは シークレットの ARN を指定します。dependsOn
パラメータ
・Fluent Bit FireLens ログルーターコンテナが開始されていることを条件とする依存関係を指定します。
Datadog オプション
キー | 設定値 | パラメータ説明 | 補足 |
---|---|---|---|
Name | datadog | 出力先 | |
Host | http-intake.logs.datadoghq.com | Datadog ログ送信先エンドポイント名 | |
TLS | on | 通信プロトコル | 安全な通信のためonが推奨です。 |
apikey | xxxxx | Datadog のAPIキー | |
compress | gzip | ペイロードの圧縮 | gzip圧縮が推奨です。 |
dd_service | webserver | ログ生成するサービス名 | サーバーの用途や役割などのわかりやすい名称での設定が推奨です。 |
dd_source | nginx | ログ生成するソース名 | ログ管理に利用されるため、ソース元となるアプリケーションやサービスの名称を設定します。 |
dd_message_key | log | message 属性に再マップする属性のキー | 特にカスタマイズを行わない場合はlogを設定します。 |
dd_tags | env:prd | ログに付与するタグ | 環境の区別のためenvタグの付与が推奨です。 |
provider | ecs | プロバイダー |
(中略)
{
"name": "nginx",
"image": "public.ecr.aws/docker/library/nginx:latest",
"cpu": 0,
"portMappings": [
{
"name": "80",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"mountPoints": [],
"volumesFrom": [],
"dependsOn": [
{
"containerName": "log_router",
"condition": "START"
}
],
"logConfiguration": {
"logDriver": "awsfirelens",
"options": {
"dd_message_key": "log",
"compress": "gzip",
"provider": "ecs",
"dd_service": "webserver",
"Host": "http-intake.logs.datadoghq.com",
"TLS": "on",
"dd_source": "nginx",
"dd_tags": "env:prd",
"Name": "datadog"
},
"secretOptions": [
{
"name": "apikey",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:xxxxxxxxxxx"
}
]
},
"systemControls": []
}
(中略)
3.Datadog サイドカーコンテナのログ構成設定(任意)
Datadog サイドカーコンテナに対してもログ構成設定を行うことで、Datadog エージェントログも Datadog に送信することができます。
datadog-agent に対してログ構成設定を行います。
secrets
パラメータ
・シークレットの ARN を指定します。logConfiguration
パラメータ
・ログドライバーはawsfirelen
を指定します。
・options
パラメータでは次の Datadog オプションを追加します。
・secretOptions
パラメータではシークレットの ARN を指定します。dependsOn
パラメータ
・Fluent Bit FireLens ログルーターコンテナが開始されていることを条件とする依存関係を指定します。
(中略)
{
"name": "datadog-agent",
"image": "public.ecr.aws/datadog/agent:latest",
"cpu": 0,
"portMappings": [],
"essential": false,
"environment": [
{
"name": "ECS_FARGATE",
"value": "true"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"secrets": [
{
"name": "DD_API_KEY",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:xxxxxxxxxxx"
}
],
"dependsOn": [
{
"containerName": "log_router",
"condition": "START"
}
],
"logConfiguration": {
"logDriver": "awsfirelens",
"options": {
"dd_message_key": "log",
"compress": "gzip",
"provider": "ecs",
"dd_service": "datadog-agent",
"Host": "http-intake.logs.datadoghq.com",
"TLS": "on",
"dd_source": "datadog-agent",
"dd_tags": "env:prd",
"Name": "datadog"
},
"secretOptions": [
{
"name": "apikey",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:xxxxxxxxxxx"
}
]
},
"systemControls": []
}
(中略)
4.ログメッセージの確認
Log Explorer でログを確認します。
一覧にコンテナのログが表示されていれば問題なく収集されています。
ログソースは nginx
となっています。
パイプラインが利用されており、様々な属性が付与されています。
dd_tags
で指定したenv:prd
というタグも付与されているのが確認できます。
CoudWatch Logs に出力したログを Datadog Forwarder でルーティングする方法
設定の流れ
AWS から Datadog にログを送信する Lambda 関数(Datadog Forwarder)を作成します。
awslogs ログドライバーを使用し、CloudWatch Logs にログを出力する設定を行います。
出力先の CloudWatch Logs ロググループにサブスクリプションフィルターを設定し、ログを Datadog にルーティングします。
必要に応じて、Datadog サイドカーコンテナにも同様のログ構成とサブスクリプションフィルター設定を適用します。
1.Datadog Forwarder 作成
下記 URL からスタック作成を行います。
DdApiKey
パラメータに Datadog APIキーを入力します。
AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。にチェックを入れ、「スタックの作成」をクリックします。
作成が完了するまで待ちます。
スタックが CREATE_COMPLETE となると、Lambda 関数「datadog-forwarder-Forwarder-xxxxxxx」が作成されます。
2.アプリケーションコンテナのログ構成設定
アプリケーションコンテナの例として、nginx に対するログ構成設定を行います。
logConfiguration
パラメータ
・ログドライバーはawslogs
を指定します。
・options のawslogs-group
awslogs-region
awslogs-stream-prefix
パラメータで出力先となる リージョン、CloudWatchLogs ロググループ名、プレフィックスを指定します。
(中略)
{
"name": "nginx",
"image": "public.ecr.aws/docker/library/nginx:latest",
"cpu": 0,
"portMappings": [
{
"name": "80",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/Forwarder/nginx",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
}
(中略)
3.アプリケーションコンテナのログに対するサブスクリプションフィルター設定
出力先となる CloudWatchLogs ロググループに対して、サブスクリプションフィルターの設定を行います。
CloudWatch メニューのロググループより、グループを選択します。
アクションから「Lambda サブスクリプションフィルターを作成」をクリックします。
作成した Datadog Forwarder を送信先の Lambda 関数に指定します。
任意のサブスクリプションフィルタ名を入力し、「ストリーミングを開始」を選択します。
4.Datadog サイドカーコンテナのログ構成設定(任意)
Datadog サイドカーコンテナに対してもログ構成設定を行うことで、Datadog エージェントログも Datadog に送信することができます。
datadog-agent に対してログ構成設定を行います。
logConfiguration
パラメータ
・ログドライバーはawslogs
を指定します。
・options のawslogs-group
awslogs-region
awslogs-stream-prefix
パラメータで出力先となる リージョン、CloudWatchLogs ロググループ名、プレフィックスを指定します。
(中略)
{
"name": "datadog-agent",
"image": "public.ecr.aws/datadog/agent:latest",
"cpu": 0,
"portMappings": [],
"essential": false,
"environment": [
{
"name": "ECS_FARGATE",
"value": "true"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"secrets": [
{
"name": "DD_API_KEY",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:xxxxxxxxxxx"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/Forwarder/datadog-agent",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
}
(中略)
5.Datadog エージェントのログに対するサブスクリプションフィルター設定(任意)
出力先となる CloudWatchLogs ロググループに対して、サブスクリプションフィルターの設定を行います。
CloudWatch メニューのロググループより、グループを選択します。
アクションから「Lambda サブスクリプションフィルターを作成」をクリックします。
作成した Datadog Forwarder を送信先の Lambda 関数に指定します。
任意のサブスクリプションフィルタ名を入力し、「ストリーミングを開始」を選択します。
6.ログメッセージの確認
Log Explorer でログを確認します。
一覧にコンテナのログが表示されていれば問題なく収集されています。
ログソースは CloudWatch
となっています。
そのため、nginx のパイプラインが利用されません。
メッセージのパースが行われず、重要度もinfo
となっています。
上記のログに対してもパイプラインとプロセッサーを利用することでメッセージのパースおよび重要度の割り当てを行うことが可能です。
詳細は以下をご参考ください。
まとめ
Amazon ECS on AWS Fargate で実行されているコンテナログを Datadog に収集する方法は以下の2つです。
- AWS FireLens を利用する方法(Datadog 推奨)
リアルタイム性が高くコスト効率が良いが、設定が複雑。 - CoudWatch Logs に出力したログを Datadog Forwarder でルーティングする方法
設定が簡単で AWS との親和性が高いが、レイテンシーや追加コストが発生。
監視や運用要件に応じて適切な方法を選択してください。
Datadog API キーは AWS Secrets Manager に登録して安全に利用するのがベストプラクティスです。
本記事が誰かのお役に立てれば幸いです。
参考